/*****************************************************************************************************
* Name          : Email Validate plugin
* Description   : A plugin that provides email validation by calling QAS Email Validate.
* Example       : $("#emailBox").emailValidate({
*                       featureVersion: "1.0",
*                       timeout: 5000,
*                       success: function (data) { },
*                       error: function (jqXHR, status, errThrown) { }  
*                    });
*****************************************************************************************************/

var emailAttempts = 0;
var validationTimeout = "120000"; 
var emailValidation; 

 (function ($, _window, undefined) {
    var pluginName = "emailValidate";

    var emailPlugin = function (element, options) {
        this.element = element;
        this.pluginName = pluginName;
        this.options = $.extend(this, {}, $.fn[pluginName].defaults, options);
    };

    emailPlugin.prototype = {
        validate: function () {
            validate.call(this);
        },
        checkDuplicate: function () {
            checkDuplicate.call(this);
        },
        reset: function () {
            this.element.val("");
        }
    };

    $.fn[pluginName] = function (options) {
        if ($(this).is("input") === false) {
            throw "Target element must be of type <input>.";
        }

        if (!$.data(this, "plugin_" + pluginName)) {
            $.data(this, "plugin_" + pluginName, new emailPlugin(this, options));
        }

        var $plugin = $.data(this, "plugin_" + pluginName);
        $plugin.checkDuplicate();
        
        return $plugin;
    };

    if (typeof validationTimeout === undefined) { 
        var validationTimeout = 5000;
    }

    $.fn[pluginName].defaults = {
        featureVersion: "1.0",
        timeout: validationTimeout,
        success: null,
        error: null
    };

    /************************
    **** PRIVATE METHODS ****
    *************************/
    function validate() {
        var $this = this;
        var email = $.trim(this.element.val());

        if (currentPlayerEmail !== email || currentPlayerEmail !== "") {
            $.ajax({
                url: emailValidationUri + "/" + encodeURI(email),
                timeout: validationTimeout,
                data: {},
                dataType: "json",
                success: function(data, status, jqXHR) {
                    onValidateSuccessHandler.call($this, data, status, jqXHR);
                },
                error: function(jqXHR, status, errThrown) {
                    onValidateErrorHandler.call($this, jqXHR, status, errThrown);
                },
                beforeSend: function(xhr) {
                    xhr.setRequestHeader("Authorization", validationAuthCode);
                },
            });
        }
    }

    function onValidateSuccessHandler(data) {
        if (!data) {
            onErrorHandler.call(this, data, "error", errorValidatingEmailMsg);
            return;
        }

        if (this.options.success && $.isFunction(this.options.success)) {
            this.options.success(data);
        }
    }

    function onValidateErrorHandler(jqXHR, status, errThrown) {
        if (this.options.error && $.isFunction(this.options.error)) {
            this.options.error(jqXHR, status, errThrown);
        }
    }

    function checkDuplicate() {
        var $this = this;
        var email = $.trim(this.element.val());

        // Only check duplicates when email is different
        if (currentPlayerEmail !== email && email !== "") {
            $.ajax({
                url: duplicateCheckEmailUri + "/" + encodeURI(email),
                timeout: validationTimeout,
                data: {},
                dataType: "json",
                success: function(data, status, jqXHR) {
                    onDuplicateSuccessHandler.call($this, data, status, jqXHR);
                },
                error: function(jqXHR, status, errThrown) {
                    onDuplicateErrorHandler.call($this, jqXHR, status, errThrown);
                },
                beforeSend: function(xhr) {
                    xhr.setRequestHeader("Authorization", validationAuthCode);
                },
            });
        }
        // Otherwise skip to validation
        else {
            validate.call(this);
        }
    }

    function onDuplicateSuccessHandler(data) {
        if(data === undefined || data === null){
            onDuplicateErrorHandler.call(this, data, "error", errorValidatingEmailMsg);
            return;
        }

        // Display message and return on duplicate email
        if(data == true)
        {
            onDuplicateErrorHandler.call(this, data, "duplicate", duplicateAcctMsg);
            return;
        }

        // Otherwise, move on to validation
        validate.call(this);
    }

    function onDuplicateErrorHandler(jqXHR, status, errThrown) {
        if (this.options.error && $.isFunction(this.options.error)) {
            this.options.error(jqXHR, status, errThrown);
        }

        // Per CSL, no locking for duplicate email attempts. Leaving commented in case they chang etheir mind
        // Lock form if we've excceded our attempts
        //emailAttempts++;
        //if (emailAttempts >= emailAttemptsBeforeFormLock) {
        //    lockForm();
        //}
    }



/*****************************************************************************************************
* Name          : emailValidation
* Description   : A class that provider email validate function to an input box.
* Methods       : validate()    - validate the email in the input box.
*                 reset()       - reset the input box.
* Example       : var email = new emailValidation(
*                     $("#emailBox"), 
*                     {
*                         featureVersion: "1.0",
*                         timeout: 5000,
*                         inlineMode: true,
*                         onSuccess: function (data) { },
*                         onError: function (jqXHR, status, errThrown),
*                         messages: {
*                               emptyEmail: "Please enter email.",
*                               error: "Please contact Experian QAS support.",
*                               timeout: "Timeout."
*                         },
*                         styles: {
*                               success: "success",
*                               successInline: "success-inline",
*                               error: "error",
*                               errorInline: "error-inline",
*                               loading: "loading",
*                               correctionEmail: "correctionEmail",
*                               emailPicklistHeader: "emailPicklistHeader",
*                               emailPicklist: "emailPicklist",
*                               picklistItem: "picklistItem",
*                               picklistItemText: "picklistItemText",
*                               closeButton: "closeButton"
*                         }
*                     };
*****************************************************************************************************/
emailValidation = function(element, options) {
    var self = this,
        $element = $(element),
        uniqueId = null,
        $plugin = null,
        emailOptions = {
            featureVersion: "1.0",
            timeout: 30000,
            inlineMode: true,
            showLoading: true,
            onSuccess: null,
            onError: null,
            messages: {},
        styles: {
            success: "success",
            successInline: "success-inline",
            error: "error",
            errorInline: "error-inline",
            loading: "loading",
            correctionEmail: "correctionEmail",
            emailPicklistHeader: "emailPicklistHeader",
            emailPicklist: "emailPicklist",
            picklistItem: "picklistItem",
            picklistItemText: "picklistItemText",
            closeButton: "closeButton"
        }
    };

    /************************
    **** PUBLIC METHODS ****
    *************************/
    // Validate the email in the input box.
    this.validate = function () {
        // Render display.
        resetStatusElement();

        if (emailOptions.showLoading) {
            renderLoadingIndicator();
        }

        $plugin = $element.emailValidate({
            proxyPath: emailOptions.proxyPath,
            featureVersion: emailOptions.featureVersion,
            timeout: emailOptions.timeout,
            success: onSuccessHandler,
            error: onErrorHandler
        });
    };

    // Reset the email validation.
    this.reset = function () {
        resetStatusElement();
        if ($plugin) {
            $plugin.reset();
        }
        $element.val("");
    };

    // Plugin options.
    this.options = emailOptions;

    /************************
    **** PRIVATE METHODS ****
    *************************/
    function resetStatusElement() {
        $element.parent().removeClass("bvalidator_error");
        $element.parent().removeClass("error-state");
        $("#emailStatus").remove();
        $("#correctionEmail").remove();
    }

    function load(options) {
        if ($element.is("input") === false) {
            throw "Target element must be of type <input>.";
        }

        $.extend(true, emailOptions, options);

        // bind when inline mode is true.
        if (emailOptions.inlineMode === true) {
            bindEvents();
        }
    }

    function bindEvents() { 
        // Bind onChange event.
        $element.change(function () {
            if (isNullOrWhiteSpace($element.val())) {
                resetStatusElement();
                showError(emailRequiredMessage);
            } else {
                self.validate();
            }
        });

        // Clear validation on form reset.
        $("#my_profile").on('reset', function () {
            resetStatusElement();  
        });
    }

    function isNullOrWhiteSpace(str) {
        return str == null || str.replace(/\s/g, '').length < 1;
    }

    // Renders our results on a successfull call to email validation
    
    function onSuccessHandler(data) {

        resetStatusElement();

        // Record our certainty
        var certainty = data.certainty;

        // Render the result
        switch (certainty)
        {
            // 100 Unknown - unknown - Accept
            case 100:
                renderVerifiedStatus();
                break;
            // 101 Unknown - timeout - Accept
            case 101:
                renderVerifiedStatus();
                break;
            // 102 Unknown - acceptAll - Accept
            case 102:
                renderVerifiedStatus();
                break;
            // 200 Disposable - disposable - Reject
            case 200:
                emailAttempts++;
                renderUnverifiedStatus(invalidEmailMsg);
                break;
            // 300 Illegitimate - Illegitimate - Accept
            case 300:
                renderVerifiedStatus();
                break;
            // 301 Illegitimate - roleAccount - Reject
            case 301:
                emailAttempts++;
                renderUnverifiedStatus(invalidEmailMsg);
                break;
            // 302 Illegitimate - typoDomain - Accept
            case 302:
                renderVerifiedStatus();
                break;
            // 400 Unreachable - unreachable - Accept
            case 400:
                renderVerifiedStatus();
                break;
            // 401 Unreachable - unresolvable - Accept
            case 401:
                renderVerifiedStatus();
                break;
            // 500 undeliverable - mailboxDisabled - Reject
            case 500:
                emailAttempts++;
                renderUnverifiedStatus(invalidEmailMsg);
                break;
            // 501 undeliverable - mailboxDoesNotExist - Reject
            case 501:
                emailAttempts++;
                renderUnverifiedStatus(invalidEmailMsg);
                break;
            // 502 undeliverable - mailboxFull -Accept
            case 502:
                renderVerifiedStatus();
                break;
            // 503 undeliverable - syntaxFailure - Reject
            case 503:
                emailAttempts++;
                renderUnverifiedStatus(invalidEmailMsg);
                break;
            // 600 Verified - verified - Accept
            case 600:
                renderVerifiedStatus();
                break;
            // Experian Email Validation is Down
            case 800:
            case 801:
            case 802:
            case 803:
            case 804:
            case 805:
            case 806:
            case 807:
            case 808:
                renderUnverifiedStatus(emailDownMsg);
                break;
            default:
                emailAttempts++;
                renderUnverifiedStatus(invalidEmailMsg);
                break;
        }

        if (emailOptions.onSuccess && $.isFunction(emailOptions.onSuccess)) {
            emailOptions.onSuccess(data);
        }

        // Lock form if we've excceded our attempts
        if(emailAttempts >= emailAttemptsBeforeFormLock)
        {
            lockForm();
        }
    }

    function renderLoadingIndicator() {
        if ($("#emailStatus").length === 1) {
            $("#emailStatus").toggleClass(emailOptions.styles.loading);
        }
        else {
            var html = [];
            html.push("<span id=\"emailStatus\" class=\"", emailOptions.styles.loading, "\"></span>");

            $element.after(html.join(""));
        }
    }



    function renderVerifiedStatus() {
      // clear errors
      $element.parent().removeClass("bvalidator_error error-state unverified-email");
        renderStatus(emailOptions.styles.successInline, emailValidatedMessage);
    }
 
    function renderUnverifiedStatus(status) {
      $element.parent().addClass("bvalidator_error error-state unverified-email");

        if (emailAttempts >= emailAttemptsBeforeFormLock) {
            renderStatus(emailOptions.styles.errorInline, threeEmailAttempts);
        }
        else
        {
            renderStatus(emailOptions.styles.errorInline, status);
        }
    }

  function renderStatus(spanClassName, message) {
    if ($("#emailStatus").length === 1) {
      $("#emailStatus").remove();
    }
    var html = [];
        html.push("<span id=\"emailStatus\" class=\"", spanClassName, "\" role=\"alert\" aria-live=\"polite\" aria-atomic=\"true\">", message, "</span>");

      $element.after(html.join(""));
      setTimeout(function () {
        $("#emailStatus").removeAttr("role");
      }, 1000);
    }

    function onErrorHandler(data, status, errThrown) {

        resetStatusElement();

        if (status === "timeout") {
            message = timeoutMsg;
        }
        else if (status === "duplicate") {
            message = duplicateAcctMsg;
            emailAttempts++;
        }
        else {
            message = errorValidatingEmailMsg;
        }

        showError(message);
    }

    function showError(message) {
      $element.parent().addClass("bvalidator_error error-state unverified-email");
        renderStatus(emailOptions.styles.errorInline, message);

        if (emailOptions.onError && $.isFunction(emailOptions.onError)) {
            emailOptions.onError(message);
        }
    }
    
    function lockForm() {
        // Only lock form on the registration page
        if ($('#registration-email-field').length > 0) {
            $(":input").attr("disabled", "disabled");
            $('#objBody_content_0_leftcolumn_0_lbSubmit').removeAttr('href');
        }
    }

    load(options);
};

})(jQuery, window);